import datetime
import time
from types import FunctionType

from django.conf import settings
from django.db.models import Q
from django.shortcuts import render, redirect, reverse
from django.contrib import messages
from django_redis import get_redis_connection
from django.utils.safestring import mark_safe

from web import models
from web.utils.group import Option, get_search_group_condition, get_choice_text
from web.utils.pager import Pagernation
from web.utils.link import filter_reverse
from web.utils.blackip import BlackIp


def get_status_text(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None):
        if is_header:
            return text
        method = 'get_%s_display' % field
        status = obj.status
        if status == 0:
            state = 'btn btn-info'
        elif status == 1:
            state = 'btn btn-danger'
        tpl = "<span class='{} btn-xs'>{}</span>".format(state, getattr(obj, method)())
        return mark_safe(tpl)

    return inner


def get_unblock_time(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None):
        if is_header:
            return text
        current_time = datetime.datetime.now()
        if obj.unblock_datetime > current_time:
            status = 'btn btn-danger'
        else:
            status = 'btn btn-success'
        unblock_datetime = obj.unblock_datetime.strftime('%Y-%m-%d %H:%M:%S')
        tpl = "<span class='{} btn-sm'>{}</span>".format(status, unblock_datetime)
        return mark_safe(tpl)

    return inner


def blockip_list(request):
    list_display = [
        'id',
        'src_ip',
        'location',
        get_choice_text('封禁设备', 'block_device'),
        get_choice_text('封禁类型', 'block_type'),
        'block_datetime',
        get_unblock_time('解封时间', 'unblock_datetime'),
        'create_user'
    ]
    model_class = models.BlockIp
    search_group = [
        Option('block_device'),
        Option('block_type')
    ]
    search_group_list = []
    for option_object in search_group:
        search_group_list.append(option_object.get_queryset_or_tuple(request, model_class))
    conn = get_search_group_condition(search_group, request)

    search_list = [
        'src_ip__contains',
        'create_user__username__contains',
        'location__contains'
    ]
    keyword = request.GET.get("keyword", "").strip()
    con = Q()
    if keyword:
        con.connector = "OR"
        for item in search_list:
            con.children.append((item, keyword))
    queryset = models.BlockIp.objects.filter(con).filter(**conn).order_by('-block_datetime')

    pager = Pagernation(request, queryset)
    # 1.处理表头
    header_list = []
    if list_display:
        for key_or_func in list_display:
            if isinstance(key_or_func, FunctionType):
                header_list.append(key_or_func(None, True))
            else:
                verbose_name = model_class._meta.get_field(key_or_func).verbose_name
                header_list.append(verbose_name)
    else:
        header_list.append(model_class._meta.model_name)
    # 2.处理表格内容
    data_list = queryset[pager.start:pager.end]
    body_list = []
    for row in data_list:
        tr_list = []
        if list_display:
            for key_or_func in list_display:
                if isinstance(key_or_func, FunctionType):
                    tr_list.append(key_or_func(row, False))
                else:
                    tr_list.append('' if getattr(row, key_or_func) == None else getattr(row, key_or_func))
        else:
            tr_list.append(row)
        body_list.append(tr_list)
    context = {
        'body_list': body_list,
        'header_list': header_list,
        'pager': pager,
        'keyword': keyword,
        'search_group_row_list': search_group_list
    }
    return render(request, 'blockip_list.html', context)


def unblock_ip(request, pk):
    blockip_obj = models.BlockIp.objects.filter(id=pk).first()

    if not blockip_obj:
        messages.add_message(request, settings.MESSAGE_DANGER_TAG, 'IP不存在')
        return redirect(filter_reverse(request, reverse('blockip_list')))

    # 将封禁IP写入redis
    src_ip = blockip_obj.src_ip
    location = blockip_obj.location
    create_datetime = blockip_obj.create_datetime
    block_type = blockip_obj.block_type
    block_device = blockip_obj.block_device
    conn = get_redis_connection('default')
    user = request.session.get(settings.MOBILEDJ_SESSION_KEY)['id']
    blackip_obj = BlackIp(src_ip, block_device, block_type, settings.UNBLOCK, user, create_datetime,location)
    conn.lpush(settings.QUEUE_TASK_NAME, str(blackip_obj))
    messages.add_message(request, messages.SUCCESS, '恶意IP：{}解封成功'.format(src_ip))
    time.sleep(1)
    return redirect(filter_reverse(request, reverse('blockip_list')))
